/* Team 5
 * James McQueen
 * Corwyn Simpson
 * May 1 ish, 2012
 */
package spider.stores;

import java.net.URL;
import java.util.Collection;
import java.util.HashSet;
import java.util.Queue;
import java.util.LinkedList;
import java.util.Set;

import spider.models.FastURL;

/**
 * Maintains a list of links that the Retriever can pull from without having to
 * check if that page has been visited before.
 * @author James McQueen
 * @author Corwyn Simpson
 */
public class LinkBuffer 
{
    /**
     * The Queue that keeps track of the order of the added links.
     */
    private Queue<URL> my_queue;
    /**
     * The Set in charge of ensuring that each page is only visited once.
     */
    private Set<FastURL> my_discovered_links;
    
    /**
     * Creates a new LinkBuffer with an empty queue and no visited links.
     */
    public LinkBuffer()
    {
        my_queue = new LinkedList<URL>();
        my_discovered_links = new HashSet<FastURL>();
    }
    
    /**
     * Adds a URL to the LinkBuffer if it has not already been added to this 
     * LinkBuffer before (even if it has been removed from the queue, it cannot
     * be added again).
     * @param the_link The link to try and add to this LinkBuffer.
     * @return True if the_link was added to the LinkBuffer.
     */
    public synchronized boolean addLink(final URL the_link)
    {
        boolean result = false;
        FastURL fast_link = new FastURL(the_link);
        if (!my_discovered_links.contains(fast_link))
        { 
            my_discovered_links.add(fast_link);
            my_queue.add(the_link);
            result = true;
        }
        return result;
    }
    
    /**
     * Adds a Collection of links to this LinkBuffer.
     * @param the_links The Collection of links to add to this LinkBuffer.
     * @see LinkBuffer.addLink(URL)
     */
    public void addAllLinks(final Collection<? extends URL> the_links)
    {
        for (URL url : the_links)
        {
            this.addLink(url);
        }
    }
    
    /**
     * Removes and returns the next link that needs to be retrieved.
     */
    public synchronized URL removeLink()
    {
        URL link = my_queue.remove();
        return link;
    }
    
    @Override
    public String toString()
    {
        StringBuilder links = new StringBuilder();
        links.append("LinkBuffer Contents");
        links.append("\n");
        for(Object link : my_queue)
        {
            links.append(link.toString());
            links.append("\n");
        }
        return links.toString();
    }

    /**
     * Returns true if the LinkBuffer is empty.
     */
    public boolean isEmpty()
    {
        return my_queue.isEmpty();
    }
    
    /**
     * Returns the number of URLs that are in the LinkBuffer.
     */
    public int size()
    {
        return my_queue.size();
    }
    
    /**
     * Returns the number of URLs that have been removed from the LinkBuffer.
     */
    public int visitedCount()
    {
        return my_discovered_links.size() - my_queue.size();
    }

    public void clear()
    {
        my_queue.clear();
        my_discovered_links.clear();
    }
}
